using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using System.Diagnostics;

namespace _1945
{
    /// <summary>
    /// This is a game component that implements IUpdateable and IDrawable.
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {

        private GraphicsDeviceManager graphics;
        private SpriteBatch spriteBatch;
        private SpriteFont spriteFont;
        private SpriteFactory spriteFactory;

        DrawableGameComponent currentScene;
        DrawableGameComponent startScene;
        DrawableGameComponent gameScene;
        DrawableGameComponent scoreScene;

        SoundEffect explode;
        SoundEffect bulletFire;
        Song startupMusic;
        Song backgroundMusic;
        Song levelMusic;


        public enum GameScenes { startScene, gameScene, scoreScene }

        private Texture2D gameSpriteSheet;
        private ScrollingBackground waterBackground;

        public Game1()
            : base()
        {
            Content.RootDirectory = "Content";
            graphics = new GraphicsDeviceManager(this);
            //graphics.PreferMultiSampling = true;
            graphics.PreferredBackBufferWidth = 800; // 1280;
            graphics.PreferredBackBufferHeight = 800;
            //graphics.IsFullScreen = true;
            //graphics.SynchronizeWithVerticalRetrace = true;
            
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Services.AddService(typeof(SpriteBatch), spriteBatch);

            spriteFont = Content.Load<SpriteFont>("gameFont");
            Services.AddService(typeof(SpriteFont), spriteFont);

            spriteFactory = SpriteFactory.Instance;
            Services.AddService(typeof(SpriteFactory), spriteFactory);

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.

            gameSpriteSheet = Content.Load<Texture2D>("1945");
            waterBackground = new ScrollingBackground(Content.Load<Texture2D>("waterbg"), BackgroundStyle.Tiled, new Vector2(0, 2));

            explode = Content.Load<SoundEffect>("explosion");
            startupMusic = Content.Load<Song>("startUp");
            backgroundMusic = Content.Load<Song>("backMusic");
            levelMusic = Content.Load<Song>("gradius3sandstorm");
            bulletFire = Content.Load<SoundEffect>("Bullets");

            gameScene = new Shooter(this, gameSpriteSheet, waterBackground, explode, bulletFire);
            startScene = new StartScene(this, gameSpriteSheet);
            scoreScene = new HighScore(this);
            currentScene = startScene;
            MediaPlayer.Play(backgroundMusic);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
            currentScene.Update(gameTime);
            base.Update(gameTime);
        }

        /// <summary>
        /// Called when the DrawableGameComponent needs to be drawn. Override this method with component-specific drawing code.
        /// Reference page contains links to related conceptual articles.
        /// </summary>
        /// <param name="gameTime">Time passed since the last call to Microsoft.Xna.Framework.DrawableGameComponent.Draw(Microsoft.Xna.Framework.GameTime).</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            currentScene.Draw(gameTime);
            
            base.Draw(gameTime);
        }

        /// <summary>
        /// Switches to different gamescene
        /// </summary>
        /// <param name="gs">Which gamescene to switch to</param>
        public void setGameScene(GameScenes gs)
        {
            switch (gs)
            {
                case GameScenes.startScene:
                    currentScene = startScene;
                    MediaPlayer.Stop();
                    break;
                case GameScenes.gameScene:
                    currentScene = gameScene;
                    gameScene = new Shooter(this, gameSpriteSheet, waterBackground, explode, bulletFire);
                    MediaPlayer.IsRepeating = true;
                    MediaPlayer.Play(levelMusic);
                    break;
                case GameScenes.scoreScene:
                    currentScene = scoreScene;
                    MediaPlayer.Stop();
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// Use when game ended, switches to scorescene
        /// </summary>
        /// <param name="scoreViewTitle">What message to display as title. GameOver / Level complete</param>
        public void gameEnded(HighScore.titleMessage t)
        {
            ((HighScore)scoreScene).setTitle(t);
            setGameScene(GameScenes.scoreScene);
        }

    }
}